package itsm.isperp.framework.utils;

/**
 * 模仿hibernate的16位UUID生成器(UUID产生是有顺序的，以便在查询未指定排序字段可以根据ID的先后产生顺序排序)
 * [性能优于java自带的UUID]---
 * <p>
 * 此id未加入ip网络标记所以理论上不是全球唯一，但是在使用上可以认为他是唯一的
 * </p>
 * <p>
 * 使用方法HibernateUUIDGenerator.generate();
 * </p>
 * 
 * @author lizx
 * @date 2013-2-8
 * @version V1.0
 */
public class HibernateUUIDGenerator {

	/**
	 * 计数器
	 */
	private static short counter = (short) 0;
	/**
	 * jvm时间
	 */
	private static final int JVM = (int) (System.currentTimeMillis() >>> 8);

	/**
	 * 生成一个序列化UUID
	 * 
	 * @return 序列化的UUID
	 */
	public static final String generate() {
		return new StringBuffer(20).append(System.nanoTime())
				.append(format(getCount())).toString();
	}

	/**
	 * 或得该类加载时jvm的时间唯一的(除非加载该类在相同德四分之一秒-几乎不可能)
	 */
	protected static final int getJVM() {
		return JVM;
	}

	/**
	 * 独特的JVM实例毫秒（除非 > Short.MAX_VALUE 创建的实例在统一毫秒）
	 */
	protected static final short getCount() {
		synchronized (HibernateUUIDGenerator.class) {
			if (counter > 9998)
				counter = 0;
			return counter++;
		}
	}

	/**
	 * 当前微秒数
	 */
	protected static final short getHiTime() {
		return (short) (System.currentTimeMillis() >>> 32);

	}

	/**
	 * 取得当前时间的毫秒值
	 * 
	 * @return 时间的毫秒值
	 */
	protected static final int getLoTime() {
		return (int) (System.currentTimeMillis());
	}

	/**
	 * 格式化数字顺序
	 * 
	 * @param intValue
	 * @return
	 */
	protected static final String format(int intValue) {
		String formatted = Integer.toHexString(intValue);
		StringBuffer buf = new StringBuffer("00000000");
		buf.replace(8 - formatted.length(), 8, formatted);
		return buf.toString();
	}

	/**
	 * 格式化数字顺序
	 * 
	 * @param shortValue
	 *            短整型的值
	 * @return 格式化字符串
	 */
	protected static final String format(short shortValue) {
		String formatted = Integer.toString(shortValue);
		StringBuffer buf = new StringBuffer("0000");
		buf.replace(4 - formatted.length(), 4, formatted);

		return buf.toString();
	}

	protected static final int toInt(byte[] bytes) {
		int result = 0;
		// 将result每次乘256 -128+ bytes[i]
		for (int i = 0; i < 4; i++) {
			result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
		}
		return result;
	}
}
